/*
 * Copyright 2011 Carnegie Mellon University
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package edu.cmu.lti.ritesdk;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;


/**
 * Sample implementation of a composite recognizer.
 * It can be used to realize one of Mixture-of-Expert models with a performance weight.
 * 
 * Caveats: A multi-engine algorithm tends to make a 
 * system to be a blackbox. We recommend you do a careful ablation study.  
 * 
 * @author Hideki Shima
 */
public class WeightedMultiEngineFramework extends AbstractRiteSystem {

  private List<AbstractRiteSystem> systems;
  private List<Double> weights;
  
  public WeightedMultiEngineFramework() {
    systems = new ArrayList<AbstractRiteSystem>();
    weights = new ArrayList<Double>();
  }
  
  public void add( AbstractRiteSystem system, double weight ) {
    systems.add(system);
    weights.add(weight);
  }
  
  @Override
  public AnalyzedTextPair run(TextPair t) {
    Map<String,Double> points = new HashMap<String,Double>(); 
    for ( int i=0; i<systems.size(); i++ ) {
      AbstractRiteSystem system = systems.get(i);
      double weight = weights.get(i);
      AnalyzedTextPair analysis = system.run(t);
      Double score = points.get( analysis.getSystemLabel() );
      if ( score == null ) score = 0D;
      score += weight * analysis.getConfidence();
      points.put( analysis.getSystemLabel(), score );
    }
    
    String argmax = null;
    double max = 0;
    for ( Entry<String,Double> e : points.entrySet() ) {
      if ( max < e.getValue() ) {
        max = e.getValue();
        argmax = e.getKey();
      }
    }
    double normalizedConfidence = max / (double)systems.size();
    
    AnalyzedTextPair result = new AnalyzedTextPair( t, argmax, normalizedConfidence );
    return result;
  }

}
